package com.ztgf.sys.service;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.ztgf.common.utils.StrUtils;
import com.ztgf.sys.common.config.YmlConfig;
import com.ztgf.sys.mapper.SysConfigMapper;
import com.ztgf.sys.models.bo.SysConfigBO;
import com.ztgf.sys.models.bo.SysConfigSaveBO;
import com.ztgf.sys.models.constant.SysConstant;
import com.ztgf.sys.models.dto.SysConfigDTO;
import com.ztgf.sys.models.dto.SysDictDTO;
import com.ztgf.sys.models.enums.SYSCodeEnum;
import com.ztgf.sys.models.service.ISysConfigService;
import com.ztgf.sys.models.vo.SysConfigVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 系统配置表控制器
 *
 * @author mxli
 * @Date 2020-05-27 10:03:34
 */
@Slf4j
@DubboService
public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfigDTO> implements ISysConfigService{

    @Resource
    private YmlConfig ymlConfig;

    @Autowired
    private SysDictServiceImpl sysDictService;


    /**
     * 分页 树形结构
     * @param bo
     * @return
     */
    @Override
    public Page<SysConfigDTO> getByInfoList(SysConfigBO bo){
        Page page = new Page(bo.getPageNo(),bo.getPageSize());
        List<SysConfigVO> sysConfigVOList = baseMapper.getByInfoList(bo);
        List<SysConfigVO> sysConfigTreeVOList = builTree(sysConfigVOList, 0L);
        List list = startPage(sysConfigTreeVOList, bo.getPageNo(), bo.getPageSize());
        page.setRecords(list);
        page.setCurrent(bo.getPageNo());
        page.setTotal(list.size());
        page.setSearchCount(true);
        return page;
    }

    /**
     * 开始分页
     * @param list
     * @param pageNum 页码
     * @param pageSize 每页多少条数据
     * @return
     */
    private static List startPage(List list, Integer pageNum,
                                 Integer pageSize) {
        if (list == null) {
            return null;
        }
        if (list.size() == 0) {
            return null;
        }

        Integer count = list.size(); // 记录总数
        Integer pageCount = 0; // 页数
        if (count % pageSize == 0) {
            pageCount = count / pageSize;
        } else {
            pageCount = count / pageSize + 1;
        }

        int fromIndex = 0; // 开始索引
        int toIndex = 0; // 结束索引

        if (pageNum != pageCount) {
            fromIndex = (pageNum - 1) * pageSize;
            toIndex = fromIndex + pageSize;
        } else {
            fromIndex = (pageNum - 1) * pageSize;
            toIndex = count;
        }

        List pageList = list.subList(fromIndex, toIndex);

        return pageList;
    }

    /**
     * 根据id获取信息
     * @param id
     * @return
     */
    @Override
    public SysConfigDTO getById(Long id){
        return baseMapper.selectById(id);
    }

    /**
     * 查询树形结构
     * @param id
     * @return
     */
    @Override
    public SysConfigVO selectById(Long id) {
        SysConfigDTO sysConfigDTO = baseMapper.selectById(id);
        if(null == sysConfigDTO){
            return null;
        }
        List<SysConfigVO> listAndChildList = getListAndChildList(id, new ArrayList<>());
        SysConfigVO sysConfigVO = new SysConfigVO();
        BeanUtils.copyProperties(sysConfigDTO,sysConfigVO);
        listAndChildList.add(sysConfigVO);
        sysConfigVO.setChildList(builTree(listAndChildList, id));
        return sysConfigVO;
    }

    private List<SysConfigVO> getListAndChildList(Long id,List<SysConfigVO> sysConfigVOList){
        List<SysConfigDTO> listByParentId = getListByParentId(id);
        for (SysConfigDTO configDTO : listByParentId) {
            getListAndChildList(configDTO.getId(),sysConfigVOList);
            SysConfigVO sysConfigVO = new SysConfigVO();
            BeanUtils.copyProperties(configDTO,sysConfigVO);
            sysConfigVOList.add(sysConfigVO);
        }
        return sysConfigVOList;
    }

    /**
     * 根据父id获取信息
     * @param id
     * @return
     */
    private List<SysConfigDTO> getListByParentId(Long id){
        Wrapper wrapper = new EntityWrapper();
        wrapper.eq("parent_id", id);
        return selectList(wrapper);
    }

    /**
     * 更新 ，包含子对象更新
     * @param bo
     */
    @Transactional
    @Override
    public boolean updateById(SysConfigBO bo) {
        Long id = bo.getId();
        SysConfigDTO sysConfigDTO = baseMapper.selectById(id);
        sysConfigDTO.setCode(bo.getCode());
        sysConfigDTO.setValue(bo.getValue());
        sysConfigDTO.setType(bo.getType());
        sysConfigDTO.setNotes(bo.getNotes());
        updateById(sysConfigDTO);
        updateAndChildById(bo.getChildList());
        return true;
    }

    /**
     * 更新 ，包含子对象
     * @param sysConfigBOStrList
     */
    private void updateAndChildById(String sysConfigBOStrList){
        if(StrUtils.isEmpty(sysConfigBOStrList)){
            return;
        }
        List<SysConfigBO> sysConfigBOList = JSONArray.parseArray(sysConfigBOStrList, SysConfigBO.class);
        for (SysConfigBO sysConfigBO : sysConfigBOList) {
            SysConfigDTO sysConfigDTO = baseMapper.selectById(sysConfigBO.getId());
            sysConfigDTO.setCode(sysConfigBO.getCode());
            sysConfigDTO.setValue(sysConfigBO.getValue());
            sysConfigDTO.setType(sysConfigBO.getType());
            sysConfigDTO.setNotes(sysConfigBO.getNotes());
            updateById(sysConfigDTO);
            updateAndChildById(sysConfigBO.getChildList());
        }
    }

    /**
     * 删除包含子对象
     * @param id
     * @return
     */
    @Transactional
    @Override
    public boolean deleteById(Long id) {
        baseMapper.deleteById(id);
        deleteAndChildInfo(id);
        return true;
    }

    private void deleteAndChildInfo(Long id){
        List<SysConfigDTO> listByParentId = getListByParentId(id);
        for (SysConfigDTO configDTO : listByParentId) {
            deleteAndChildInfo(configDTO.getId());
            baseMapper.deleteById(configDTO.getId());
        }
    }

    /**
     * 插入或者更新
     * @param bo
     * @return
     */
    @Transactional
    @Override
    public boolean insert(SysConfigBO bo) {
        Long id = bo.getId();
        if(null == id){//所有都是保存
            SysConfigSaveBO sysConfigSaveBO = new SysConfigSaveBO();
            BeanUtils.copyProperties(bo,sysConfigSaveBO);
            Long aLong = addAndReturnId(sysConfigSaveBO);
            insertAndChildById(bo.getChildList(),aLong);
        }else{//下面的内容可能保存可能删除可能更新
            updateOrInsertOrDelete(bo.getChildList(),id);
        }
        return true;
    }

    /**
     * 更新删除或者保存
     * @param sysConfigBOStrList
     * @param parentId
     */
    private void updateOrInsertOrDelete(String sysConfigBOStrList,Long parentId){
        if(StrUtils.isEmpty(sysConfigBOStrList)){
            return;
        }
        //删除相关联的数据
        deleteById(parentId);
        List<SysConfigBO> sysConfigBOList = JSONArray.parseArray(sysConfigBOStrList,SysConfigBO.class);
        for (SysConfigBO sysConfigBO : sysConfigBOList) {
            SysConfigSaveBO sysConfigSaveBO = new SysConfigSaveBO();
            BeanUtils.copyProperties(sysConfigBO,sysConfigSaveBO);
            sysConfigSaveBO.setParentId(parentId);
            Long id = addAndReturnId(sysConfigSaveBO);
            updateOrInsertOrDelete(sysConfigBO.getChildList(),id);
        }
    }

    /**
     * 插入 ，包含子对象
     * @param sysConfigBOStrList
     */
    private void insertAndChildById(String sysConfigBOStrList,Long parentId){
        if(StrUtils.isEmpty(sysConfigBOStrList)){
            return;
        }
        List<SysConfigBO> sysConfigBOList = JSONArray.parseArray(sysConfigBOStrList,SysConfigBO.class);
        for (SysConfigBO sysConfigBO : sysConfigBOList) {
            SysConfigSaveBO sysConfigSaveBO = new SysConfigSaveBO();
            BeanUtils.copyProperties(sysConfigBO,sysConfigSaveBO);
            sysConfigSaveBO.setParentId(parentId);
            Long id = addAndReturnId(sysConfigSaveBO);
            insertAndChildById(sysConfigBO.getChildList(),id);
        }
    }

    @Override
    public boolean add(SysConfigSaveBO saveBO) {
        SysConfigDTO dto = new SysConfigDTO();
        BeanUtils.copyProperties(saveBO,dto);
        Long id = ymlConfig.getPkId();
        dto.setId(id);
        return this.insert(dto);
    }

    public Long addAndReturnId(SysConfigSaveBO saveBO) {
        SysConfigDTO dto = new SysConfigDTO();
        BeanUtils.copyProperties(saveBO,dto);
        Long id = ymlConfig.getPkId();
        dto.setId(id);
        this.insert(dto);
        return id;
    }

    /**
     * 根据code获取权限
     * @param code
     * @return
     */
    @Override
    public SysConfigDTO getByCode(String code) {
        SysConfigDTO sysConfigDTO = new SysConfigDTO();
        sysConfigDTO.setCode(code);
        sysConfigDTO.setStatus(SYSCodeEnum.ENABLE_1.getCode());
        return baseMapper.selectOne(sysConfigDTO);
    }

    @Override
    public Long getLongByCode(String code) {
        SysConfigDTO dto = getByCode(code);
        if(dto == null){
            return null;
        }
        try{
            return Long.parseLong(dto.getValue());
        } catch (Exception e) {
            log.error("getLongByCode is error:" + code, e);
        }
        return null;
    }

    @Override
    public BigDecimal getBigDecimalByCode(String code) {
        SysConfigDTO dto = getByCode(code);
        if(dto == null){
            return BigDecimal.ZERO;
        }
        try{
            return BigDecimal.valueOf(Double.parseDouble(dto.getValue()));
        } catch (Exception e) {
            log.error("getBigDecimalByCode is error:" + code, e);
        }
        return BigDecimal.ZERO;
    }

    @Override
    public List<SysConfigDTO> getCancelOrderList() {
        SysDictDTO sysDictDTO = sysDictService.getByName(SysConstant.CANCEL_ORDER_STR);
        String value = sysDictDTO.getValue();//取消订单父id
        if(StrUtils.isEmpty(value)){
            return new ArrayList<>();
        }
        return getListByParentId(Long.parseLong(value));
    }


    //建立树形结构
    public List<SysConfigVO> builTree(List<SysConfigVO> menuList, Long id){
        List<SysConfigVO> treeMenus =new ArrayList<>();
        for(SysConfigVO menuNode : getRootNode(menuList,id)) {
            menuNode=buildChilTree(menuNode,menuList);
            treeMenus.add(menuNode);
        }
        return treeMenus;
    }

    //递归，建立子树形结构
    private SysConfigVO buildChilTree(SysConfigVO pNode, List<SysConfigVO> menuList){
        List<SysConfigVO> chilMenus =new ArrayList<>();
        for(SysConfigVO menuNode : menuList) {
            if(menuNode.getParentId().equals(pNode.getId())) {
                chilMenus.add(buildChilTree(menuNode,menuList));
            }
        }
        pNode.setChildList(chilMenus);
        return pNode;
    }

    //获取根节点
    private List<SysConfigVO> getRootNode(List<SysConfigVO> menuList,Long id) {
        List<SysConfigVO> rootMenuLists =new  ArrayList<>();
        for(SysConfigVO menuNode : menuList) {
            if(menuNode.getParentId().equals(id)) {
                rootMenuLists.add(menuNode);
            }
        }
        return rootMenuLists;
    }
}
